/**
 * 目的：声明多个类里拥有共同的一个方法，方便若有函数要调用该方法时，传参类型声明不需要一大堆类的联合类型了
  getArea方法只有声明没有实现体
  实现让子类自己实现
  可以将getArea方法定义为抽象方法: 在方法的前面加abstract
  抽象方法必须出现在抽象类中, 类前面也需要加abstract
 */

abstract class Shape {
  abstract getArea();
}

class Rectangle extends Shape {
  constructor(public width: number, public height: number) {
    super();
  }

  getArea() {
    return this.width * this.height;
  }
}

class Circle extends Shape {
  constructor(public radius: number) {
    super();
  }

  getArea() {
    return this.radius ** 2 * Math.PI;
  }
}

class Triangle extends Shape {
  getArea() {
    return 100;
  }
}

// 通用的函数
function calcArea(shape: Shape) {
  return shape.getArea();
}

calcArea(new Rectangle(10, 20));
calcArea(new Circle(5));
calcArea(new Triangle());

// 在Java中会报错: 不允许
calcArea({ getArea: function () {} });

// 抽象类不能被实例化
// calcArea(new Shape())
// calcArea(100)
// calcArea("abc")
